#pragma once
#include<iostream>
#include<string>
#include<memory>
#include<jsoncpp/json/json.h>
#include<functional>
#include"Socket.hpp"
#include"Log.hpp"

using namespace LogModule;
using namespace SocketModule;

class Request
{
    public:
    Request()
    {}
    Request(int x,int y,char oper):_x(x),_y(y),_oper(oper)
    {
    }
    std::string Serialize()
    {
        Json::Value root;
        root["x"]=_x;
        root["y"]=_y;
        root["oper"]=_oper;

        Json::FastWriter write;
        std::string s=write.write(root);
        return s;
    }
    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ret=reader.parse(in,root);
        if(ret)
        {
            _x=root["x"].asInt();
            _y=root["y"].asInt();
            _oper=root["oper"].asInt();
        }
        return ret;
    }
    ~Request(){};
    int X(){return _x;};
    int Y(){return _y;};
    int Oper(){return _oper;};
    private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
    public:
    Response(){}
    Response(int result,int code):_result(result),_code(code)
    {
    }
    std::string Serialize()
    {
        Json::Value root;
        root["result"]=_result;
        root["code"]=_code;
        Json::FastWriter write;
        return write.write(root); 
    }
    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader read;
        bool ret=read.parse(in,root);
        if(ret)
        {
            _result=root["result"].asInt();
            _code=root["code"].asInt();
        }
        return ret;
    }
    ~Response(){}
    void SetResult(int result)
    {
        _result=result;
    }
    void SetCode(int code)
    {
        _code=code;
    }
    void ShowResult()
    {
        std::cout<<"最终的计算结果为:"<<_result<<":["<<_code<<"]"<<std::endl;
    }
    private:
    int _result;
    int _code;
};

const std::string sep="\r\n";
using func_t=std::function<Response(Request& rep)>;

class Protocol
{
    public:
    Protocol(){}
    Protocol(func_t func):_func(func)
    {}
    //把一个 JSON 字符串封装成带长度头的自定义协议方便 TCP 接收端正确拆包
    std::string Encode(const std::string& jsonstr)
    {
        std::string len=std::to_string(jsonstr.size());
        return len+sep+jsonstr+sep;
    }
    //buffer中将一个报文的数据取出添加到package,并且在buffer中删除
    bool Decode(std::string& buffer,std::string* package)
    {
        LOG(LogLevel::DEBUG)<<"ENTER IN PROTOCOL DECODE";
        ssize_t pos=buffer.find(sep);
        if(pos==std::string::npos)
        {
            return false;
        }
        std::string package_len_str=buffer.substr(0,pos);
        LOG(LogLevel::DEBUG)<<"PACKAGE_LEN_STR:"<<package_len_str;

        int package_len_int=std::stoi(package_len_str);

        int target_len=package_len_str.size()+package_len_int+2*sep.size();
        if(buffer.size()<target_len)
        {
            return false;
        }
        *package=buffer.substr(pos+sep.size(),package_len_int);
        buffer.erase(0,target_len);
        return true;
    }

    //将package反序列化为resquest,再转化成response,在序列化成Json字符串,再形成报文返回
    std::string Excute(std::string& package)
    {
        LOG(LogLevel::DEBUG)<<"进入到PROTOCOL EXECUTE BEGIN";
        Request req;
        bool ok=req.Deserialize(package);
        if(!ok)
        {
            return "";
        }
        Response resp=_func(req);

        std::string json_str=resp.Serialize();

        std::string send_str=Encode(json_str);

        LOG(LogLevel::DEBUG)<<"进入到PROTOCOL EXECUTE END";
        return send_str;
    }
    ~Protocol()
    {}
    private:

    //这个_func已经使用Cal构建过了,处理request,并返回response
    func_t _func;
};